package ProducerAndConsumer;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ProducerAndConsumer02 {
    public static void main(String[] args) {
        Task02 task = new Task02();

        new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                task.printA();
            }
        }).start();

        new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                task.printB();
            }
        }).start();

        new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                task.printC();
            }
        }).start();
    }
}

/**
 * 三个线程，交替打印数字
 *
 * 注：await方法会将锁释放，三条线程会不停的抢锁，抢到锁之后判断执行条件，只有满足执行条件的时候才能执行业务！！！
 */
class Task02 {
    // lock锁和三个不同的执行条件
    private final ReentrantLock lock = new ReentrantLock();
    private final Condition condition1 = lock.newCondition();
    private final Condition condition2 = lock.newCondition();
    private final Condition condition3 = lock.newCondition();

    // 执行标志位，0，1，2分别为三条线程的执行条件
    private int flag = 0;

    private int num = 0;

    public void printA() {
        lock.lock();

        try {
            // 等待条件
            while (flag != 0) {
                condition1.await();
            }

            // 执行业务
            System.out.println("大家好，我是" + Thread.currentThread().getName() + "，我要打印" + num++);
            flag = 1;

            // 唤醒
            condition2.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void printB() {
        lock.lock();

        try {
            // 等待
            while (flag != 1) {
                condition2.await();
            }

            // 执行业务
            System.out.println("大噶好啊，我是" + Thread.currentThread().getName() + "，我要打印" + num++);
            flag = 2;

            // 唤醒
            condition3.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void printC() {
        lock.lock();

        try {
            // 等待
            while (flag != 2) {
                condition3.await();
            }

            // 执行业务
            System.out.println("雷猴啊，我是" + Thread.currentThread().getName() + "，我要打印" + num++);
            System.out.println("雷猴啊，我是" + Thread.currentThread().getName() + "，锁" + lock.getHoldCount());
            flag = 0;

            // 唤醒
            condition1.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

    }
}